package codegen.util.database;

import java.sql.Blob;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;

public enum DataType {
	TYPE_INT {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			String value = rs.getString(seqNo);
			if (value != null) {
				return new Integer(rs.getInt(seqNo));
			}
			return null;
		}

		public String getClassName() {
			return "Integer";
		}

		public String getShortName() {
			return "Int";
		}

		public String toAlignString() {
			return "right";
		}
		public String getHibernateTypeString() {
			return "java.lang.Integer";
		
		}
		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			if (value == null) {
				pstmt.setNull(seqNo, Types.INTEGER);
			} else {
				pstmt.setInt(seqNo, (Integer) value);
			}
		}

		public String toDispString(Object value) {

			return value == null ? "" : new DecimalFormat("#,##0;-#,##0")
					.format(value);
		}

		public String getTypeString() {
			return "Integer";
		}

	},
	TYPE_LONG {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			String value = rs.getString(seqNo);
			if (value != null) {
				return rs.getLong(seqNo);
			}
			return null;
		}

		public String getClassName() {
			return "Long";
		}

		public String getShortName() {
			return "Long";
		}

		public String toAlignString() {
			return "right";
		}
		public String getHibernateTypeString() {
			return "java.lang.Long";
		
		}
		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			if (value == null) {
				pstmt.setNull(seqNo, Types.INTEGER);
			} else {
				pstmt.setInt(seqNo, (Integer) value);
			}
		}

		public String toDispString(Object value) {

			return value == null ? "" : new DecimalFormat("#,##0;-#,##0")
					.format(value);
		}

		public String getTypeString() {
			return "Integer";
		}

	},
	TYPE_DOUBLE {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			String value = rs.getString(seqNo);
			if (value != null) {
				return rs.getDouble(seqNo);
			}
			return null;
		}

		public String getClassName() {
			return "Double";
		}

		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			if (value == null) {
				pstmt.setNull(seqNo, Types.DECIMAL);
			} else {
				pstmt.setDouble(seqNo, (Double) value);
			}
		}

		public String toAlignString() {
			return "right";
		}

		public String toDispString(Object value) {
			return value == null ? "" : new DecimalFormat("#,##0.00;-#,##0.00")
					.format(value);
		}

		public String getTypeString() {
			return "Double";
		}
		public String getHibernateTypeString() {
			return "java.lang.Double";
		
		}
	},
	TYPE_CHAR {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			String value = rs.getString(seqNo);
			if (value != null) {
				return rs.getDouble(seqNo);
			}
			return null;
		}

		public String getClassName() {
			return "String";
		}

		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			if (value == null) {
				pstmt.setNull(seqNo, Types.DECIMAL);
			} else {
				pstmt.setDouble(seqNo, (Double) value);
			}
		}

		public String toAlignString() {
			return "right";
		}

		public String toDispString(Object value) {
			return value == null ? "" : value.toString();
		}

		public String getTypeString() {
			return "String";
		}
	},
	
	TYPE_MONEY {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			String value = rs.getString(seqNo);
			if (value != null) {
				return rs.getDouble(seqNo);
			}
			return null;
		}

		public String getClassName() {
	
			return "BigDecimal";
		}
		public String getHibernateTypeString() {
			return "java.math.BigDecimal";
		
		}
		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			if (value == null) {
				pstmt.setNull(seqNo, Types.DECIMAL);
			} else {
				pstmt.setBigDecimal(seqNo, (java.math.BigDecimal)value);
			}
		}

		public String toAlignString() {
			return "right";
		}

		public String toDispString(Object value) {
			return value == null ? "" : new DecimalFormat("#,##0.00;-#,##0.00")
					.format(value);
		}

		public String getTypeString() {
			return "BigDecimal";
		}
	},
	TYPE_VARCHAR {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			return rs.getString(seqNo);
		}
		public String getHibernateTypeString() {
			return "java.lang.String";
		}
		public String getClassName() {
			return "String";
		}

		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			pstmt.setString(seqNo, value.toString());
		}

		public String toDispString(Object value) {
			return value == null ? "" : value.toString();
		}

		public String getTypeString() {
			return "String";
		}
	},
	TYPE_DATE {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			return rs.getDate(seqNo);
		}

		public String getClassName() {
			return "Date";
		}

		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			pstmt.setDate(seqNo, (Date) value);
		}

		public String toDispString(Object value) {
			return value == null ? "" : new SimpleDateFormat("yyyyMMdd")
					.format(value);
		}

		public String getTypeString() {
			return "java.sql.Date";
		}

	},
	TYPE_TIMESTAMP {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			return rs.getTimestamp(seqNo);
		}

		public String getClassName() {
			return "Timestamp";
		}

		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			pstmt.setTimestamp(seqNo, (Timestamp) value);
		}

		public String toDispString(Object value) {
			return value == null ? "" : new SimpleDateFormat(
					"yyyyMMdd HH:mm:ss").format(value);
		}

		public String getTypeString() {
			return "java.sql.Timestamp";
		}

	},

	TYPE_TIME {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			return rs.getTime(seqNo);
		}

		public String getClassName() {
			return "Time";
		}

		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			pstmt.setTime(seqNo, (Time) value);
		}

		public String toDispString(Object value) {
			return value == null ? "" : new SimpleDateFormat("HH:mm:ss")
					.format(value);
		}

		public String getTypeString() {
			return "java.sql.Time";
		}
	},
	TYPE_CLOB {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			return rs.getBlob(seqNo);
		}

		public String getClassName() {
			return "Clob";
		}

		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			pstmt.setBlob(seqNo, (Blob) value);
		}

		public String toDispString(Object value) {
			return value == null ? "" :"Clob...";
		}

		public String getTypeString() {
			return "java.sql.Clob";
		}
	},
	TYPE_BLOB {
		public Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
				throws SQLException {
			return rs.getBlob(seqNo);
		}

		public String getClassName() {
			return "Blob";
		}

		public void setValueForPreparedStatement(PreparedStatement pstmt,
				int seqNo, Object value) throws SQLException {
			pstmt.setBlob(seqNo, (Blob) value);
		}

		public String toDispString(Object value) {
			return value == null ? "" :"Blob...";
		}

		public String getTypeString() {
			return "java.sql.Blob";
		}
	};

	public String toAlignString() {
		return "center";
	}

	public abstract Object getObjectValueFromResultSet(ResultSet rs, int seqNo)
			throws SQLException;

	abstract public String getClassName();

	public String getShortName() {
		return getClassName();
	}

	/**
	 * PreparedStatement
	 * 
	 * @param pstmt
	 * @param seqNo
	 * @param value
	 * @throws SQLException
	 */
	public abstract void setValueForPreparedStatement(PreparedStatement pstmt,
			int seqNo, Object value) throws SQLException;

	public static DataType transfer(int type, int width, int decimalWidth, String columName) {
		
		//System.out.println("DataType transfer:" + type + "    " + width + "     "+ decimalWidth);
		//System.out.println("width:"+ width + "  ---- decimalWidth:" + decimalWidth);
		//System.out.println("columName:"+ columName);
		switch (type) {
		case Types.BIGINT:
			return TYPE_LONG;
		case Types.SMALLINT:
		case Types.INTEGER:
		case Types.BOOLEAN:
			return TYPE_INT;
		case Types.DECIMAL:
		case Types.DOUBLE:
		case Types.FLOAT:
		case Types.NUMERIC://ORACLE 中NUMERIC定义包含多种数据类型,难以对其所有进行控制,故根据项目需要定义其返回值
			//根据字段命名规则返回类型
			if(columName.equals("ID") || columName.endsWith("_ID")){
				return TYPE_LONG;
			}else if(columName.startsWith("IS_")){
				return TYPE_INT;
			} else if(columName.endsWith("_NO")){
				return TYPE_LONG;
			}else if(columName.endsWith("_AMT") || columName.endsWith("_PCT")){
				return TYPE_DOUBLE;
			}else if(columName.endsWith("_QTY")){
				return TYPE_INT;
			}else if (width == 1 && decimalWidth == 0) {
				return TYPE_INT;
			}else if (width == 4 && decimalWidth == 0) {//日期年月格式
				return TYPE_INT;
			}else if (width == 0 && decimalWidth == -127) {
				return TYPE_LONG;
			}else if (decimalWidth > 0) {
				//return TYPE_MONEY;
				return TYPE_DOUBLE;
			}
			return TYPE_DOUBLE;
		case Types.CHAR:
		case Types.VARCHAR:
		case Types.LONGVARCHAR:
			return TYPE_VARCHAR;
		case Types.TIME:
		case Types.TIMESTAMP:
		case Types.DATE:
			return TYPE_DATE;
		case Types.CLOB:
			return TYPE_CLOB;
		default:
			return TYPE_VARCHAR;
		}
	}
	/*public static DataType transfer(int type, int width, int decimalWidth) {
		switch (type) {
		case Types.BIGINT:
			return TYPE_LONG;
		case Types.SMALLINT:
		case Types.INTEGER:
		case Types.BOOLEAN:
			return TYPE_INT;
		case Types.CHAR:
			return TYPE_VARCHAR;
		case Types.DATE:
			return TYPE_DATE;
		case Types.DECIMAL:
		case Types.DOUBLE:
		case Types.FLOAT:
		case Types.NUMERIC:
			if (width < 12 && decimalWidth == 0) {
				return TYPE_INT;
			}
			else if (decimalWidth > 0) {
				return TYPE_MONEY;
			}
			return TYPE_DOUBLE;
		case Types.VARCHAR:
		case Types.LONGVARCHAR:
			return TYPE_VARCHAR;
		case Types.TIME:
			return TYPE_TIME;
		case Types.TIMESTAMP:
			return TYPE_TIMESTAMP;
		case Types.BLOB:
			return TYPE_BLOB;
		case Types.CLOB:
			return TYPE_CLOB;
		default:
			return TYPE_VARCHAR;
		}
	}*/

	public abstract String getTypeString();

	public String toSqlString(Object value) {
		if (value == null) {
			return "NULL";
		}
		return value.toString();
	}

	public String toAjaxString(Object value) {
		if (value == null) {
			return "NULL";
		}
		return value.toString();
	}

	public abstract String toDispString(Object value);

	public String getHibernateTypeString() {
		return this.getTypeString();
	}

}
